package triIndex.btree;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import transaction.Transaction;

public class BRoot {

	private int order;
		
	private BNode node;
	
	private NodeFactory factory;
	
	private ReadWriteLock rwlock;
	private Lock rlock;
	private Lock wlock;

	public BRoot(int order, NodeFactory factory) {
		this.order = order;
		this.factory = factory;
		
		rwlock = new ReentrantReadWriteLock();
		rlock = rwlock.readLock();
		wlock = rwlock.writeLock();
	}
	
	public void setNode(BNode node) {
		wlock.lock();
		this.node = node;
		wlock.unlock();
	}

	public void insert(int key, int value, Transaction tx) {
		wlock.lock();
		try {
			BNode[] nodes = node.insert(key, value, tx);
			if (nodes.length == 1) {
				factory.save(nodes[0], tx);
				node = nodes[0];
				return ;
			}

			BNode root = factory.createNewBranch(this.order, tx); 
		
			if (nodes[0].isLeaf && nodes[1].isLeaf) 
				root.keys.add(nodes[0].keys.lastElement());
			else if (!nodes[0].isLeaf && !nodes[1].isLeaf) 
				root.keys.add(nodes[0].keys.remove(nodes[0].keys.size() - 1));
			else 
				System.err.println("Should not be reached, in index.btree.Broot");
		
			root.values.add(nodes[0].nodeId);
			root.values.add(nodes[1].nodeId);
			root.childnum = 2;
		
			factory.save(nodes[0], tx);
			factory.save(nodes[1], tx);
			factory.save(root, tx);
			
			factory.unPin(nodes[0]);
			factory.unPin(nodes[1]);
			//factory.unPin(node);
		
			node = root;
			/*
			System.out.println(">>> with key = " + key + " <<< ROOT");
			node.output();
			System.out.println(">>>  <<<");
			*/
		}
		finally {
			wlock.unlock();
		}
	}

	public int find(int key, Transaction tx) {
		rlock.lock();
		try {
			return node.find(key, tx);
		}
		finally {
			rlock.unlock();
		}
	}

	public int getRootNodeId() {
		return this.node.nodeId;
	}
}
